package server;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;

import org.bminfo.migle.filemanage.*;
import org.bminfo.migle.parser.CommandExecutor;

public class MigleServerImpl implements IMigleServer {
	
	String miGLE_home = "";
	String moopPath = "";
	String tempRoot = "";
	
	public void setmiGLEHome(String path){
		miGLE_home = path.replace("\\", "/");
		moopPath = miGLE_home + "WEB-INF/classes/org/bminfo/migle/miGLE/";
		tempRoot = miGLE_home + "temp/";
		System.out.println(moopPath);
	}
	
	String folderName;
	String tempPath;

	public String initialization(String filename, String filecontent) throws IOException{
	
		FileProducer fileProducer = new FileProducer();
		folderName = fileProducer.folderNameProducer();
		
		System.out.println("Creating the foldername:" + folderName);
		
//		System.out.println(miGLE_home);
//		System.out.println(moopPath);
//		System.out.println(tempRoot);
		
		tempPath = tempRoot + folderName + "/";
		
		File folder = new File(tempPath);
		if (folder.mkdir() == false){
			folder.mkdir();
			System.out.println("make dir");
		}
		
		File gbfile = new File(tempPath + filename);
		PrintWriter wr = new PrintWriter(new BufferedWriter(new FileWriter(gbfile)));
		wr.write(filecontent);
		wr.close();
		
		File htmlfolder = new File(tempPath + "list/");
		System.out.println(tempPath + "list/");
		if (htmlfolder.mkdir() == false){
			htmlfolder.mkdir();
			System.out.println("make dir");
		}
		
		return folderName;
	}
	
	public String[] utr3ProEx(String gbfile) throws IOException{
		
/*	These codes is for windows with perl scripts
		String cmd_UTR3ProEx = "perl " + "\"" + moopPath + "UTR3ProEx.pl"
		+ "\" \"" + tempPath + "sequence.gb" + "\" \"" + tempPath + "\"";
*/
		
///* These codes is for linux with perl scripts
		String cmd_UTR3ProEx = "perl " + moopPath + "UTR3ProEx.pl" + " "
		+ tempPath + "sequence.gb" + " " + tempPath;
// */
		
/* These codes is for windows and linux with executable files
		String cmd_UTR3ProEx = "UTR3ProEx "
		+ tempPath + "sequence.gb" + " " + tempPath;
 */
		
		System.out.println(cmd_UTR3ProEx);
		
		MigleServerImpl step1 = new MigleServerImpl();
		
		step1.cmdExec(cmd_UTR3ProEx);
		
		File utrfile = new File(tempPath + "seq.fasta");
		
		BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(utrfile)));
		String line = null;
		String[] data = new String[3];
		String start = null;
		Integer length= 0;
		StringBuffer lines = new StringBuffer();
		while((line = br.readLine()) != null){
			if(line.startsWith(">")){
				start = line.substring(line.lastIndexOf("|")+1,line.length());
				lines.append(line + "\n");
			}
			else{
				length+= line.length();
				//System.out.println(length.toString());
				lines.append(line + "\n");
			}
		}
		data[0] = Integer.valueOf(Integer.parseInt(start) + 1).toString();
		data[1] = Integer.valueOf(Integer.parseInt(start) + length).toString();;
		data[2] = lines.toString();
		br.close();
		
		System.out.println(data[0] + " " + data[1] + " " + data[2]);
		return data;
	}
	
	public void pointMut(String start, String end) throws IOException{
		
		System.out.println(tempPath);
		
///*	These codes is for windows with perl scripts
		String cmd_PointMut = "perl " + "\"" + moopPath + "pointMut.pl"
		+ "\" \"" + tempPath + "seq.fasta" + "\" " + start + " " + end
		+ " \"" + tempPath + "\"";
//*/

/* These codes is for linux with perl scripts
		String cmd_PointMut = "perl " + moopPath + "pointMut.pl" + " "
		+ tempPath + "seq.fasta" + " " + start + " " + end
		+ " " + tempPath;
 */

/* These codes is for windows and linux with executable files
		String cmd_PointMut = "pointMut "
		+ tempPath + "seq.fasta" + " " + start + " " + end
		+ " " + tempPath;
 */
		
		System.out.println(cmd_PointMut);
		
		MigleServerImpl step2 = new MigleServerImpl();
		
		step2.cmdExec(cmd_PointMut);
	}
	
	public void pointMut(int site, String iupac_char, String filetype, String indel, String indel_string) throws IOException{
		
		System.out.println(tempPath);
		
		Map<String, String> iupac = new HashMap<String,String>();
		iupac.put("A", "A");
		iupac.put("C", "C");
		iupac.put("G", "G");
		iupac.put("T", "T");
		iupac.put("M", "AC");
		iupac.put("R", "AG");
		iupac.put("W", "AT");
		iupac.put("S", "CG");
		iupac.put("Y", "CT");
		iupac.put("K", "GT");
		iupac.put("V", "ACG");
		iupac.put("H", "ACT");
		iupac.put("D", "AGT");
		iupac.put("B", "CGT");
		iupac.put("N", "ACGT");
		
//		>rs5186|miGLE|SNP|site=301|length=601|alleles=A/C|Origin
//		gtatagcttattttaacaattgcctgaatcctcttttttatggctttctggggaaaaaatttaaaagatattttctccagcttctaaaatatattcccccaaaagccaaatcccactcaaacctttcaacaaaaatgagcacgctttcctaccgcccctcagataatgtaagctcatccaccaagaagcctgcaccatgttttgaggttgagtgacatgttcgaaacctgtccataaagtaattttgtgaaagaaggagcaagagaacattcctctgcagcacttcactaccaaatgagcattagctacttttcagaattgaaggagaaaatgcattatgtggactgaaccgacttttctaaagctctgaacaaaagcttttctttccttttgcaacaagacaaagcaaagccacattttgcattagacagatgacggctgctcgaagaacaatgtcagaaactcgatgaatgtgttgatttgagaaattttactgacagaaatgcaatctccctagcctgcttttgtcctgttattttttatttccacataaaggtatttagaatatattaaatcgttagaggagcaacaggagatgaga
//
//		>291|c->A|pointMut
//		aagagaacattcctctgcagcacttcactaAcaaatgagcattagctacttttcagaattg
//		>291|c->T|pointMut
//		aagagaacattcctctgcagcacttcactaTcaaatgagcattagctacttttcagaattg
//		>291|c->G|pointMut
//		aagagaacattcctctgcagcacttcactaGcaaatgagcattagctacttttcagaattg
		
		BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(tempPath + "seq.fasta" )));
		PrintWriter wr = new PrintWriter(new BufferedWriter(new FileWriter(tempPath + "pointmut")));
		
		String line = null;
		String head = "";
        StringBuilder seq = new StringBuilder();
       	int startSeq = 1;
		
//        >gi|122939142|miGLE|3'UTR|Start=1081|Length=894|CodonStart|1|CdsLength|1080 
        
		while((line = br.readLine()) != null){
			if(line.startsWith(">")){
				head = line + "|Origin";
			}else{
				seq.append(line.toLowerCase());
			}
		}

		if(head.contains("|miGLE|3\'UTR|")){
			String[] field = head.split("\\|");
			startSeq = Integer.parseInt(field[4].replace("Start=", ""));
		}
		
   		String sequence = seq.toString();
   		int length = sequence.length();
   		int startRange = site-10;
       	int endRange = site+10;

       	if(startRange < startSeq){
       		startRange = startSeq;
       	}
       	if(endRange > (startSeq + length -1)){
       		endRange = startSeq + length -1;
       	}
       	
       	int windowLength = 30;
 		
		wr.write(head + "\n");
		wr.write(sequence + "\n\n");
		
       	if(indel.equals("insert")){
       		int mutStart = site - windowLength;
       		int mutEnd = site + windowLength;
       		
           	if(mutStart < startSeq){
           		mutStart = startSeq;
           	}
           	if(mutEnd > (startSeq + length -1)){
           		mutEnd = startSeq + length -1;
           	}
           	
           	String range = sequence.substring(mutStart-startSeq, mutEnd-startSeq+1);
           	
           	wr.write(">" + site + "|" + "N" + "->" + "\'-\'" + "|pointMut\n");
           	wr.write(range + "\n");
           	
   			range = sequence.substring(mutStart-startSeq, site-startSeq)
           				+ indel_string
           				+ sequence.substring(site-startSeq+1, mutEnd-startSeq+1);
           	wr.write(">" + site + "|" + "N" + "->" + indel_string + "|pointMut\n");
           	wr.write(range + "\n");
       		wr.write("\n");
       	}else {
       	
       	for(int i=startRange; i<=endRange; i++ ){
       		
       		int mutStart = i - windowLength;
       		int mutEnd = i + windowLength;
       		
           	if(mutStart < startSeq){
           		mutStart = startSeq;
           	}
           	if(mutEnd > (startSeq + length -1)){
           		mutEnd = startSeq + length -1;
           	}
           	
           	if(filetype.equals("snp") && i == site){
           		String iupac_list = iupac.get(iupac_char);
           		for(int j=0; j<iupac_list.length(); j++){
           			if(iupac_list.toLowerCase().charAt(j) != sequence.charAt(i-startSeq)){
           				String range = sequence.substring(mutStart-startSeq, i-startSeq)
           						+ iupac_list.charAt(j)
           						+ sequence.substring(i-startSeq+1, mutEnd-startSeq+1);
           				wr.write(">" + i + "|" + sequence.charAt(i-startSeq) + "->" + iupac_list.charAt(j) + "|pointMut\n");
           				wr.write(range + "\n");
           				wr.flush();
           			}
           		}
           		wr.write("\n");
           	}else{
           		String atgc_list = "ATGC";
           		for(int j=0; j<atgc_list.length(); j++){
           			if(atgc_list.toLowerCase().charAt(j) != sequence.charAt(i-startSeq)){
           				String range = sequence.substring(mutStart-startSeq, i-startSeq)
           						+ atgc_list.charAt(j)
           						+ sequence.substring(i-startSeq+1, mutEnd-startSeq+1);
           				wr.write(">" + i + "|" + sequence.charAt(i-startSeq) + "->" + atgc_list.charAt(j) + "|pointMut\n");
           				wr.write(range + "\n");
           				wr.flush();
           			}
           		}
           		wr.write("\n");
           	}
       	}
       	}
       	
       	br.close();
       	wr.close();

	}
	
	public void miranda(String go, String ge, String en, String sc, String snp) throws IOException {

///* These codes is for windows with perl scripts
 
		String cmd_Miranda = "\"" + moopPath + "miranda" + "\" \"" + moopPath + "hsa-mature-miR.fasta" + "\" "
								+ "pointmut" + " -go " + go +" -ge " + ge + " -en " + en + " -sc " + sc
								+ " -out " + "mirandaRlt.txt";
		
		String cmd_ParMirRlt = "perl " + "\"" + moopPath + "parMirRlt.pl"
								+ "\" -snp " + snp + " " + "mirandaRlt.txt"
								+ " " + "seq.fasta"	+ " ./";
		
		String cmd_GetTarget = "\"" + moopPath + "getTarget " + "\" " + "parseRlt.txt" + " "
								+ " rtable.txt report.txt moopsbar.js " + " \""
								+ moopPath + "moopsbarTemplate.js" + "\"";
//*/

/* These codes is for linux with perl scripts
		 
		String cmd_Miranda = "miranda" + " " + moopPath + "hsa-mature-miR.fasta"
								+ " " + tempPath + "pointmut"
								+ " -go " + go +" -ge " + ge + " -en " + en + " -sc " + sc
								+ " -out " + tempPath + "mirandaRlt.txt";
		
		String cmd_ParMirRlt = "perl " + moopPath + "parMirRlt.pl"
								+ " -snp " + snp + " " + tempPath + "mirandaRlt.txt"
								+ " " + tempPath + "seq.fasta"
								+ " " + tempPath;
		
		String cmd_GetTarget = "getTarget " + tempPath + "parseRlt.txt" + " "
								+ tempPath + "rtable.txt" + " "
								+ tempPath + "report.txt" + " "
								+ tempPath + "moopsbar.js" + " "
								+ moopPath + "moopsbarTemplate.js";
*/
		
/* These codes is for windows and linux with executable files
 
		String cmd_Miranda = "miranda " + moopPath + "hsa-mature-miR.fasta"
		+ " " + tempPath + "pointmut"
		+ " -go " + go +" -ge " + ge + " -en " + en + " -sc " + sc
		+ " -out " + tempPath + "mirandaRlt.txt";

		
		String cmd_ParMirRlt = "parMirRlt "
		+ "-snp " + snp + " " + tempPath + "mirandaRlt.txt"
		+ " " + tempPath + "seq.fasta"
		+ " " + tempPath;
		
		String cmd_GetTarget = "getTarget " + tempPath + "parseRlt.txt" + " "
		+ tempPath + "rtable.txt" + " "
		+ tempPath + "report.txt" + " "
		+ tempPath + "moopsbar.js" + " "
		+ moopPath + "moopsbarTemplate.js";
*/

		System.out.println(cmd_Miranda);
		System.out.println(cmd_ParMirRlt);
		System.out.println(cmd_GetTarget);
		
		System.out.println(miGLE_home);
		
//		MigleServerImpl step3 = new MigleServerImpl();		
//
//		step3.cmdExec(cmd_Miranda);
//		System.out.println("Finish 3");
//		step3.cmdExec(cmd_ParMirRlt);
//		System.out.println("Finish 4");
//		step3.cmdExec(cmd_GetTarget);
//		System.out.println("Finish 5");
		
		CommandExecutor exe = new CommandExecutor();
		exe.cmdExec(cmd_Miranda, tempPath);
		exe.cmdExec(cmd_ParMirRlt, tempPath);
		exe.cmdExec(cmd_GetTarget, tempPath);
		
	}
	
	public void copyMigleFile(){
		FileOperate fo = new FileOperate();
		fo.copyFile(moopPath + "showmoops.jsp", tempPath + "showmoops.jsp");
		fo.copyFile(moopPath + "nchart.js", tempPath + "nchart.js");
		fo.copyFile(moopPath + "canvaschart.css", tempPath + "canvaschart.css");
		fo.copyFile(moopPath + "cygwin1.dll", tempPath + "cygwin1.dll");
		fo.copyFile(moopPath + "load.jsp", tempPath + "load.jsp");		
	}
	
	public void exSingleInfo(String site, String type) throws IOException{

///* These code is for windows with perl scrpit
		String cmd_ExSingleInfo = "perl " + "\"" + moopPath + "ExSingleInfo.pl"
		+ "\" \"" + tempPath + "report.txt" + "\" "
		+ site + " " + type + " \"" + tempPath + "list/\"";
//*/
		
/* These code is for windows with perl scrpit
		String cmd_ExSingleInfo = "perl " + moopPath + "ExSingleInfo.pl"
		+ " " + tempPath + "report.txt" + " "
		+ site + " " + type + " " + tempPath + "list/";
*/
		
/* These coding is for windows and linux with executable files
		String cmd_ExSingleInfo = "ExSingleInfo "
		+ tempPath + "report.txt" + " "
		+ site + " " + type + " " + tempPath + "list/";
*/
		
		System.out.println(cmd_ExSingleInfo);
		
		MigleServerImpl step5 = new MigleServerImpl();
		
		step5.cmdExec(cmd_ExSingleInfo);
		
	}

	
	public void setPath(String foldername){

		folderName = foldername;
		tempPath = tempRoot + folderName + "/";	
		System.out.println(foldername);
		System.out.println(folderName);
		System.out.println(tempPath);
	}
	
	public synchronized void cmdExec(String cmdName) throws IOException{

		Process proc = Runtime.getRuntime().exec(cmdName); 

		String str;
		BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(proc.getInputStream())); 
		while ( (str=bufferedReader.readLine()) != null)
			System.out.println(str); 

		try{
			System.out.println(proc.waitFor());
			System.out.println("Wait!");
		}catch(InterruptedException e){
			System.out.println("These is an Interrupted Exception!");
		}
	}
}